package com.shelpe.services.sinbad.entity.jpa;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.AttributeConverter;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.shelpe.services.sinbad.entity.BaseJpaEntity;
import com.shelpe.services.sinbad.service.utils.EntityUtils;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Entity(name = "tactics")
@Data
@EqualsAndHashCode(callSuper = true)
public class Tactics extends BaseJpaEntity {
	public final static int DEVICE_PC = 2;
	public final static int DEVICE_MOBILE = 1;

	@Id
	@Column(name = "tactics_id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private long tacticsID;
	@Column(name = "user_id")
	private long userID;
	@Column(name = "tactics_name")
	private String name;
	@Column(name = "tactics_status")
	@Convert(converter = StatusConverter.class)
	private Status status;
	private int executions;
	@Convert(converter = PremiumConverter.class)
	private Premium premium;
	private int campaignPeriod;
	private int heighestPrice;
	@Column(name = "keyword_ids")
	private String keywordIDs;
	@Column(name = "tactics_create_time")
	@Convert(converter = EntityUtils.Day2IntConverter.class)
	private Date createTime;
	@Column(name = "tactics_modified_time")
	@Convert(converter = EntityUtils.Day2IntConverter.class)
	private Date modifiedTime;
	private String path;
	@Column(name = "`from`")
	@Convert(converter = EntityUtils.Day2StringConverter.class)
	private Date fromTime;
	@Column(name = "`to`")
	@Convert(converter = EntityUtils.Day2StringConverter.class)
	private Date toTime;
	private Date nextTime;
	@Column(name = "schedule_period")
	// @Convert(converter = SchedulePeriodConverter.class)
	private String schedulePeriod = "";
	@Column(name = "day_period")
	private String dayPeriod = "";

	private int device;
	@Convert(converter = ModeConverter.class)
	private Mode mode;// 卡位模式

	@Column(name = "valid_executions")
	private int validExecutions; // 有效执行次数
	@Column(name = "tactics_valid_time")
	private Date validTime; // 有效执行时间

	@Temporal(TemporalType.DATE)
	@Column(name = "from_date")
	private Date fromDate;
	@Temporal(TemporalType.DATE)
	@Column(name = "to_date")
	private Date toDate;

	@Data
	public static class SchedulePeriod {
		private List<Range> ranges;

		public void addRange(Range range) {
			if (this.ranges == null) {
				this.ranges = new ArrayList<Range>();
			}
			this.ranges.add(range);
		}
	}

	@Data
	public static class Range {
		@JsonFormat(shape = Shape.STRING, pattern = "HH:mm")
		private String from;
		@JsonFormat(shape = Shape.STRING, pattern = "HH:mm")
		private String to;
	}

	@Data
	public static class Premium {
		private float value;
		private boolean percent;

		public int nextPrice(int price, int sign) {
			if (percent) {
				if (Math.floor(price * (value * sign + 100) / 100) == price) {
					price = (int) Math.ceil(price * (value * sign + 100) / 100);
				} else {
					price = (int) (price * (value * sign + 100) / 100);
				}
			} else {
				price = price + (int) (value * sign);
			}
			return price;
		}
	}

	public static enum Mode {
		manual("manual"), auto("auto");
		private String value;

		private Mode(String v) {
			this.value = v;
		}

		public String getValue() {
			return this.value;
		}

		public static Mode from(String value) {
			Mode en = Mode.manual;
			for (Mode s : Mode.values()) {
				if (s.getValue().equals(value)) {
					en = s;
					break;
				}
			}
			return en;
		}
	}

	public static enum Status {
		starting(1), pause(2), finish(3);
		private int value;

		private Status(int v) {
			this.value = v;
		}

		public int getValue() {
			return this.value;
		}
	}

	public static class ModeConverter implements AttributeConverter<Mode, String> {

		@Override
		public String convertToDatabaseColumn(Mode attribute) {
			return attribute != null ? attribute.getValue() : "manual";
		}

		@Override
		public Mode convertToEntityAttribute(String dbData) {
			if (StringUtils.isNotBlank(dbData)) {
				return Mode.from(dbData);
			}
			return null;
		}
	}

	public static class SchedulePeriodConverter implements AttributeConverter<SchedulePeriod, String> {

		@Override
		public String convertToDatabaseColumn(SchedulePeriod attribute) {
			return EntityUtils.fromSchedulePeriod(attribute);
		}

		@Override
		public SchedulePeriod convertToEntityAttribute(String dbData) {
			return EntityUtils.toSchedulePeriod(dbData);
		}
	}

	public static class PremiumConverter implements AttributeConverter<Premium, String> {

		@Override
		public String convertToDatabaseColumn(Premium attribute) {
			if (attribute != null) {
				return attribute.getValue() + (attribute.percent ? "%" : "");
			}
			return null;
		}

		@Override
		public Premium convertToEntityAttribute(String dbData) {
			if (dbData != null) {
				Premium p = new Premium();
				if (dbData.contains("%")) {
					dbData = dbData.replace("%", "");
					p.percent = true;
				}
				p.value = NumberUtils.toFloat(dbData);
				return p;
			}
			return null;
		}

	}

	public static class StatusConverter implements AttributeConverter<Status, Integer> {

		@Override
		public Integer convertToDatabaseColumn(Status attribute) {
			return attribute != null ? attribute.getValue() : Status.starting.getValue();
		}

		@Override
		public Status convertToEntityAttribute(Integer dbData) {
			Status status = Status.starting;
			for (Status s : Status.values()) {
				if (s.getValue() == dbData) {
					status = s;
					break;
				}
			}
			return status;
		}
	}

}
